security.tsx 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112
  1. import { useParams } from 'common'
  2. import { useMemo, useState } from 'react'
  3. import { LoadingLine } from 'ui'
  4. import { LINTER_LEVELS } from '@/components/interfaces/Linter/Linter.constants'
  5. import { lintInfoMap } from '@/components/interfaces/Linter/Linter.utils'
  6. import { LinterDataGrid } from '@/components/interfaces/Linter/LinterDataGrid'
  7. import LinterFilters from '@/components/interfaces/Linter/LinterFilters'
  8. import { LinterPageFooter } from '@/components/interfaces/Linter/LinterPageFooter'
  9. import LintPageTabs from '@/components/interfaces/Linter/LintPageTabs'
  10. import AdvisorsLayout from '@/components/layouts/AdvisorsLayout/AdvisorsLayout'
  11. import { DefaultLayout } from '@/components/layouts/DefaultLayout'
  12. import { FormHeader } from '@/components/ui/Forms/FormHeader'
  13. import { Lint, useProjectLintsQuery } from '@/data/lint/lint-query'
  14. import { useSelectedProjectQuery } from '@/hooks/misc/useSelectedProject'
  15. import { DOCS_URL } from '@/lib/constants'
  16. import type { NextPageWithLayout } from '@/types'
  17. const ProjectLints: NextPageWithLayout = () => {
  18. const { preset, id } = useParams()
  19. const { data: project } = useSelectedProjectQuery()
  20. // need to maintain a list of filters for each tab
  21. const [filters, setFilters] = useState<{ level: LINTER_LEVELS; filters: string[] }[]>([
  22. { level: LINTER_LEVELS.ERROR, filters: [] },
  23. { level: LINTER_LEVELS.WARN, filters: [] },
  24. { level: LINTER_LEVELS.INFO, filters: [] },
  25. ])
  26. const [currentTab, setCurrentTab] = useState<LINTER_LEVELS>(
  27. (preset as LINTER_LEVELS) ?? LINTER_LEVELS.ERROR
  28. )
  29. const {
  30. data,
  31. isPending: isLoading,
  32. isRefetching,
  33. refetch,
  34. } = useProjectLintsQuery({
  35. projectRef: project?.ref,
  36. })
  37. const activeLints = (data ?? []).filter((lint) => lint.categories.includes('SECURITY'))
  38. // hide vulnerable_postgres_version lint temporarily
  39. // https://linear.app/briven/project/pg-minor-version-upgrade-for-security-vulnerabilities-0124b2c2dcf5
  40. // https://github.com/briven/briven/pull/38280/files
  41. //.filter((lint) => lint.name !== 'vulnerable_postgres_version')
  42. const currentTabFilters = (filters.find((filter) => filter.level === currentTab)?.filters ||
  43. []) as string[]
  44. const filteredLints = activeLints
  45. .filter((x) => x.level === currentTab)
  46. .filter((x) => (currentTabFilters.length > 0 ? currentTabFilters.includes(x.name) : x))
  47. const filterOptions = lintInfoMap
  48. // only show filters for lint types which are present in the results and not ignored
  49. .filter((item) =>
  50. activeLints.some((lint) => lint.name === item.name && lint.level === currentTab)
  51. )
  52. .map((type) => ({
  53. name: type.title,
  54. value: type.name,
  55. }))
  56. const selectedLint: Lint | null = useMemo(() => {
  57. return activeLints.find((lint) => lint.cache_key === id) ?? null
  58. }, [id, activeLints])
  59. return (
  60. <div className="h-full flex flex-col">
  61. <FormHeader
  62. className="py-4 px-6 -mb-px!"
  63. title="Security Advisor"
  64. docsUrl={`${DOCS_URL}/guides/database/database-linter`}
  65. />
  66. <LintPageTabs
  67. activeLints={activeLints}
  68. isLoading={isLoading}
  69. currentTab={currentTab}
  70. setCurrentTab={setCurrentTab}
  71. />
  72. <LinterFilters
  73. filterOptions={filterOptions}
  74. filteredLints={filteredLints}
  75. activeLints={activeLints}
  76. currentTab={currentTab}
  77. filters={filters}
  78. isLoading={isLoading || isRefetching}
  79. setFilters={setFilters}
  80. onClickRefresh={refetch}
  81. />
  82. <LoadingLine loading={isRefetching} />
  83. <LinterDataGrid
  84. filteredLints={filteredLints}
  85. currentTab={currentTab}
  86. selectedLint={selectedLint}
  87. isLoading={isLoading}
  88. />
  89. <LinterPageFooter
  90. hideDbInspectCTA
  91. isLoading={isLoading}
  92. isRefetching={isRefetching}
  93. refetch={refetch}
  94. />
  95. </div>
  96. )
  97. }
  98. ProjectLints.getLayout = (page) => (
  99. <DefaultLayout>
  100. <AdvisorsLayout title="Linter">{page}</AdvisorsLayout>
  101. </DefaultLayout>
  102. )
  103. export default ProjectLints